package com

import grails.converters.JSON
import java.text.DateFormat
import java.text.SimpleDateFormat
import groovy.sql.Sql

class ContasCorrenteController {

	def dataSource
	def criaContaContabilService

	static allowedMethods = [save: "POST", update: "POST", delete: "POST"]

	def index = {
		redirect(action: "list", params: params)
	}

	def list = {
		params.max = Math.min(params.max ? params.int('max') : 10, 100)
		[contasCorrenteInstanceList: ContasCorrente.list(params), contasCorrenteInstanceTotal: ContasCorrente.count()]
	}

	def create = {
		def contasCorrenteInstance = new ContasCorrente()
		contasCorrenteInstance.properties = params
		return [contasCorrenteInstance: contasCorrenteInstance]
	}

	def save = {
		def contasCorrenteInstance = new ContasCorrente(params)
		if(criaContaContabilService.criaContaContabilContaCorrente(contasCorrenteInstance)){
			println "FornecedorController.save: -- Salvo fornecedor: "+ contasCorrenteInstance + " e criou conta contabil para ele!!"
			
			flash.message = "${message(code: 'default.created.message', args: [message(code: 'contasCorrente.label', default: 'ContasCorrente'), contasCorrenteInstance.id])}"
			redirect(action: "show", id: contasCorrenteInstance.id)
		}
		else {
			render(view: "create", model: [contasCorrenteInstance: contasCorrenteInstance])
		}
	}

	def show = {
		def contasCorrenteInstance = ContasCorrente.get(params.id)
		if (!contasCorrenteInstance) {
			flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'contasCorrente.label', default: 'ContasCorrente'), params.id])}"
			redirect(action: "list")
		}
		else {
			[contasCorrenteInstance: contasCorrenteInstance]
		}
	}

	def edit = {
		def contasCorrenteInstance = ContasCorrente.get(params.id)
		if (!contasCorrenteInstance) {
			flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'contasCorrente.label', default: 'ContasCorrente'), params.id])}"
			redirect(action: "list")
		}
		else {
			return [contasCorrenteInstance: contasCorrenteInstance]
		}
	}

	def update = {
		def contasCorrenteInstance = ContasCorrente.get(params.id)
		if (contasCorrenteInstance) {
			if (params.version) {
				def version = params.version.toLong()
				if (contasCorrenteInstance.version > version) {

					contasCorrenteInstance.errors.rejectValue("version", "default.optimistic.locking.failure", [
						message(code: 'contasCorrente.label', default: 'ContasCorrente')]
					as Object[], "Another user has updated this ContasCorrente while you were editing")
					render(view: "edit", model: [contasCorrenteInstance: contasCorrenteInstance])
					return
				}
			}
			contasCorrenteInstance.properties = params
			if (!contasCorrenteInstance.hasErrors() && contasCorrenteInstance.save(flush: true)) {
				flash.message = "${message(code: 'default.updated.message', args: [message(code: 'contasCorrente.label', default: 'ContasCorrente'), contasCorrenteInstance.id])}"
				redirect(action: "show", id: contasCorrenteInstance.id)
			}
			else {
				render(view: "edit", model: [contasCorrenteInstance: contasCorrenteInstance])
			}
		}
		else {
			flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'contasCorrente.label', default: 'ContasCorrente'), params.id])}"
			redirect(action: "list")
		}
	}

	def delete = {
		def contasCorrenteInstance = ContasCorrente.get(params.id)
		if (contasCorrenteInstance) {
			try {
				contasCorrenteInstance.delete(flush: true)
				flash.message = "${message(code: 'default.deleted.message', args: [message(code: 'contasCorrente.label', default: 'ContasCorrente'), params.id])}"
				redirect(action: "list")
			}
			catch (org.springframework.dao.DataIntegrityViolationException e) {
				flash.message = "${message(code: 'default.not.deleted.message', args: [message(code: 'contasCorrente.label', default: 'ContasCorrente'), params.id])}"
				redirect(action: "show", id: params.id)
			}
		}
		else {
			flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'contasCorrente.label', default: 'ContasCorrente'), params.id])}"
			redirect(action: "list")
		}
	}

	def conciliacao = {
		def contasCorrenteInstance = new ContasCorrente()
		contasCorrenteInstance.properties = params

		List<ContasCorrente>contasCorrenteList = ContasCorrente.list()

		return [contasCorrenteInstance: contasCorrenteInstance, contasCorrenteList:contasCorrenteList]
	}

	public double apuraSaldo(int conta){
		
		//montando SQLs para apuração do saldo
		int contaId = conta

		println("DATASOURCE " + dataSource)
		def sql = new Sql(dataSource)


		def queryApuraCreditos = "select sum(valor+acrescimo) as creditos from contas_receber"
		queryApuraCreditos += " where baixada = true and conta_corrente_id = :contaCorrenteId"

		def paramsApuraCreditos = [contaCorrenteId: contaId]

		def creditos = sql.rows(queryApuraCreditos, paramsApuraCreditos)
        double credito

		if (creditos.creditos[0] == null){
			println("TO AQUIIII")
			credito = 0
		} else {
		    credito = Double.parseDouble(creditos.creditos[0].toString())
        }

		def queryApuraDebitos = "select sum(valor+acrescimo) as debitos from contas_pagar"
		queryApuraDebitos += " where baixada = true and conta_corrente_id = :contaCorrenteId"

		def debitos = sql.rows(queryApuraDebitos, paramsApuraCreditos)
		double debito
		
		if (debitos.debitos[0] == null){
			println("TO AQUIIII")
			debito = 0
		}else{
			debito = Double.parseDouble(debitos.debitos[0].toString())
		}
				
		return credito - debito
	}

	/**
	 * Descrição Recebe uma conta corrente e monta uma lista com todas as contas que se tem para pagar ou receber 
	 * @author alex e João Paulo
	 * @param contaCorrente
	 * @return lista de contas a pagar e receber ordenado por data de vencimento
	 *  
	 */
	def conciliaContas = {
		def contasCorrenteInstance = new ContasCorrente()
		String donoGasto = ""
		int idContaCorrente = Integer.parseInt(params.contaCorrente.id)

		contasCorrenteInstance = ContasCorrente.get(idContaCorrente)
		List contasList = new ArrayList()

		def sql = new Sql(dataSource)

		def queryListContasPagarReceber = " select id, data_vencimento, valor, venda_id, 'C' from contas_receber where baixada=0 union select id,"

		queryListContasPagarReceber +="data_vencimento, valor, gasto_id, 'D' from contas_pagar where baixada=0 order by data_vencimento asc;"

		def contas = sql.rows(queryListContasPagarReceber)

		double saldo = apuraSaldo(idContaCorrente)
		double saldoPendente = saldo
		println ("Saldo"+saldo)
		contas.each{ conta ->

			if (conta.C == 'C'){
				Venda venda = Venda.get(conta.venda_id)
				donoGasto = venda.cliente.nome
				saldoPendente = saldoPendente + conta.valor
			}else{
				Gastos gasto = Gastos.get(conta.venda_id)
				donoGasto = gasto.fornecedor.nome
				saldoPendente = saldoPendente - conta.valor
			}

			contasList.add(contaId: conta.id,
					descricao: donoGasto,
					dataVencimento: conta.data_vencimento,
					tipo: conta.C,
					valor: conta.valor,
					saldoPendente: saldoPendente,
					acrescimo: null
					)
		}
		return [contasCorrenteInstance: contasCorrenteInstance, contasList:contasList, saldo: saldo]
	}

	/**
	 * Descrição recebe uma conta e baixa ela em uma conta corrente 
	 * @author alex
	 * @param contaCorrente, contaReceber ou ContaPagar
	 * @return 
	 */
	def baixaContas = {

		def contas = params.conta
		println("PEGOU DO PARAMS"+ contas.getClass())

		int idContaCorrente = Integer.parseInt(params.contaCorrente)
		ContasCorrente contaCorrente = ContasCorrente.get(idContaCorrente)

		if (params.contaTipo == "C"){
			ContasReceber contaReceber = ContasReceber.findById(params.contaId)
			println ("SALVANDO CONTA RECEBER: "+contaReceber)
			contaReceber.baixada = true
			contaReceber.dataBaixa = new Date()
			contaReceber.contaCorrente = contaCorrente
		}else{

			ContasPagar contaPagar = ContasPagar.get(params.contaId)
			println ("SALVANDO CONTA RECEBER: "+contaPagar)
			contaPagar.baixada = true
			contaPagar.dataBaixa = new Date()
			contaPagar.contaCorrente = contaCorrente
		
		}

		redirect(action: "conciliaContas", params:["contaCorrente.id": idContaCorrente])
	}
}
